package il.ac.tau.cvws.scrabblesidekick.server.engine.scrabble.detector;

import il.ac.tau.cvws.scrabblesidekick.server.engine.dictionary.exception.DictionaryException;
import il.ac.tau.cvws.scrabblesidekick.server.util.exception.ExceptionConstant;
import il.ac.tau.cvws.scrabblesidekick.server.util.exception.ScrabbleSidekickException;
import il.ac.tau.cvws.scrabblesidekick.shared.constant.BoardConstants;
import il.ac.tau.cvws.scrabblesidekick.shared.datatype.WordPlacement;
import il.ac.tau.cvws.scrabblesidekick.shared.datatype.game.Direction;
import il.ac.tau.cvws.scrabblesidekick.shared.datatype.game.Position;
import il.ac.tau.cvws.scrabblesidekick.shared.datatype.game.Rack;
import il.ac.tau.cvws.scrabblesidekick.shared.datatype.game.TileLayout;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

public class HorizontalSolutionDetector extends SolutionDetector
{	
	/*
	 * LOGIC: The function search for the valid Horizontal results for the current layout on board and user's rack. The function uses the given dictionary from DB to find these words.
	 * 		  First of all the function finds the maximal row and the minimal row by iterating over the layout boundries points.
	 * 		  Next, the function iterate each row (between the minimal and maximal row found before) and define a length for a pattern from 2 to 15. 
	 * 		  Then, the function iterate over each cell on row and search for a template in the predefined length, where a template must consist at least one tile non-empty. 
	 * 		  when the function finds such template it calls findSolution that retrieve the right solution (as explained there) and validate each retrieved answer by calling validateSolution. 
	 * INPUT:layoutBoundries- all points that have at least one free cell in adjacent to them a, layout-  Set of all existing tiles on board,  dictionaryId- identifier of language in DB, rack - user's rack
	 * RETURN: the function return all horizontal suggestion for the current rack and layout.
	 * NOTICE: when the language order is not from left to right (e.g hebrew) some reverse operation are done in order to search correctly the words in DB
	 */
	@Override
	public List<WordPlacement> detect(Set<Position> layoutBoundries, TileLayout layout, int dictionaryId, Rack rack) throws ScrabbleSidekickException
	{
		int minRow = Integer.MAX_VALUE;
		int maxRow = 0;
		
		List<WordPlacement> solList = new ArrayList<WordPlacement>();
		
		boolean isLeft2Right = false;
		
		try
		{
			isLeft2Right = dbEngine.isLeft2RightDictionary(dictionaryId);
		}
		catch (SQLException e)
		{
			throw new DictionaryException(ExceptionConstant.GENERAL_FAILURE);
		} 

		for(Position p : layoutBoundries)
		{
			if(p.getRow() < minRow)
			{
				minRow = p.getRow();
			}

			if(p.getRow() > maxRow)
			{
				maxRow = p.getRow();
			}
		}

		for (int i = minRow; i < maxRow; i++)
		{
			for (int currWidth =  BoardConstants.BOARD_TILES_NUM ; currWidth >= 2 ; currWidth--)
			{
				for (int j = 0; j + currWidth <= BoardConstants.BOARD_TILES_NUM; j++)
				{
					Set<Position> positions = layout.asPostitionSet();
					boolean exist = false;
			
					for (Position p: positions)
					{
						if (j <= p.getColumn() && p.getColumn() < j + currWidth && p.getRow() == i)
						{
							exist = true; 
							break;
						}
					}

					if (exist)
					{
						Position startPos 		   = new Position(i, j );
						List<Integer> wordTemplate = createWordTemplate(layout,startPos , currWidth, Direction.HORIZONTAL);

						if(isLeft2Right == false)
						{
							Collections.reverse(wordTemplate);
						}
						
						List<int[]> possibleSolutions =  findSolutions(rack , wordTemplate, dictionaryId);

						if(possibleSolutions.size() == 0)
						{
							continue;
						}
						else
						{
							for( int[] sol : possibleSolutions)
							{
								if(isLeft2Right == false)
								{
									for(int k = 0; k < Math.round(sol.length / 2.0); k++)
									{
										int temp;
										temp = sol[k];
										sol[k] = sol[sol.length - k - 1];
										sol[sol.length - k - 1] = temp;
									}
								}
								
								if(validateSolution(sol, layout, startPos, currWidth, Direction.HORIZONTAL, dictionaryId, isLeft2Right))
								{
									solList.add( new WordPlacement(layout.asIndices(), sol, startPos, Direction.HORIZONTAL));
								}
							}
						}
					}
				}
			}
		}

		return solList;
	}

}
